import os

import yaml

from common import constants, env, AsciiCode
from common.util import Util


class ConfigurationFactory:
    conf_name = Util.ascii_to_string(AsciiCode.ASCII_CONF_NAME_KEY)
    conf_suffix = Util.ascii_to_string(AsciiCode.ASCII_CONF_SUFFIX_KEY)
    conf_encoding = "utf-8"

    @classmethod
    def load_configuration(cls):
        conf_dir = Util.unified_static_path(constants.CONF_DIRECTORY)
        main_conf_path = Util.get_file_path(conf_dir, f'{cls.conf_name}.{cls.conf_suffix}')
        with open(main_conf_path, 'r', encoding=cls.conf_encoding) as file:
            config = yaml.load(file, Loader=yaml.FullLoader)
            p_key = Util.ascii_to_string(AsciiCode.ASCII_CONF_PROFILES_KEY)
            a_key = Util.ascii_to_string(AsciiCode.ASCII_CONF_ACTIVE_KEY)
            active_profile = config.get(p_key, {}).get(a_key, 'default')
            active_profile = os.getenv(env.PROFILES_ACTIVE, active_profile)
        config_file = f'{cls.conf_name}-{active_profile}.{cls.conf_suffix}'
        active_config_path = Util.get_file_path(conf_dir, config_file)
        with open(active_config_path, 'r', encoding=cls.conf_encoding) as file:
            active_config = yaml.load(file, Loader=yaml.FullLoader)
            # merged_config = {**config, **active_config}
        merged_config = cls.__merge_dicts(config, active_config)
        merged_config = cls.__override_with_env(merged_config)
        return merged_config

    @classmethod
    def __merge_dicts(cls, d1, d2):
        if d2 is None:
            return d1
        for key in d2:
            if key in d1 and isinstance(d1[key], dict) and isinstance(d2[key], dict):
                cls.__merge_dicts(d1[key], d2[key])
            else:
                d1[key] = d2[key]
        return d1

    @classmethod
    def __override_with_env(cls, config):
        """
        暂时仅限有默认值的配置项才能使用，否者将出现异常；后续可以考虑优化
        """
        # 覆盖 server 配置
        config['server']['host'] = os.getenv(env.SERVER_HOST, config['server'].get('host', "localhost"))
        config['server']['port'] = os.getenv(env.SERVER_PORT, config['server'].get('port', "4000"))
        # 覆盖 Redis 配置
        config['redis']['host'] = os.getenv(env.REDIS_HOST, config['redis'].get('host', "localhost"))
        config['redis']['port'] = os.getenv(env.REDIS_PORT, config['redis'].get('port', 6379))
        config['redis']['user_name'] = os.getenv(env.REDIS_USERNAME, config['redis'].get('user_name', "default"))
        config['redis']['pass_word'] = os.getenv(env.REDIS_PASSWORD, config['redis'].get('pass_word', ""))
        return config


conf = ConfigurationFactory.load_configuration()


class ConfigAttribute:

    @staticmethod
    def _get_config_value(section_key, attribute_key, default=None):
        return conf.get(section_key, {}).get(attribute_key, default)

    @staticmethod
    def get_server_host():
        return ConfigAttribute._get_config_value("server", "host", "localhost")

    @staticmethod
    def get_server_port():
        return ConfigAttribute._get_config_value("server", "port", "4000")

    @staticmethod
    def get_enable_fill():
        return ConfigAttribute._get_config_value("server", "enable_fill", False)

    @staticmethod
    def get_enable_minio():
        return ConfigAttribute._get_config_value("server", "enable_minio", False)

    @staticmethod
    def get_enable_cache():
        return ConfigAttribute._get_config_value("server", "enable_cache", False)

    @staticmethod
    def get_sms_endpoint():
        return ConfigAttribute._get_config_value("sms", SMS_ENDPOINT_ATT)

    @staticmethod
    def get_sms_sign_name():
        return ConfigAttribute._get_config_value("sms", SMS_SIGN_NAME_ATT)

    @staticmethod
    def get_sms_phone_numbers():
        return ConfigAttribute._get_config_value("sms", SMS_PHONE_NUMBERS_ATT)

    @staticmethod
    def get_ding_open_conversation_id():
        return ConfigAttribute._get_config_value("ding", DING_OPEN_CONVERSATION_ID_ATT)

    @staticmethod
    def get_ding_app_key():
        return ConfigAttribute._get_config_value("ding", DING_APP_KEY_ATT)

    @staticmethod
    def get_ding_app_secret():
        return ConfigAttribute._get_config_value("ding", DING_APP_SECRET_ATT)

    @staticmethod
    def get_ding_robot_code():
        return ConfigAttribute._get_config_value("ding", DING_ROBOT_CODE_ATT)

    @staticmethod
    def get_minio_endpoint():
        return ConfigAttribute._get_config_value("minio", "endpoint")

    @staticmethod
    def get_minio_access_key():
        return ConfigAttribute._get_config_value("minio", "access_key")

    @staticmethod
    def get_minio_secret_key():
        return ConfigAttribute._get_config_value("minio", "secret_key")

    @staticmethod
    def get_redis_host():
        return ConfigAttribute._get_config_value("redis", "host", "localhost")

    @staticmethod
    def get_redis_port():
        return ConfigAttribute._get_config_value("redis", "port", 6379)

    @staticmethod
    def get_redis_username():
        return ConfigAttribute._get_config_value("redis", "user_name", "default")

    @staticmethod
    def get_redis_password():
        return ConfigAttribute._get_config_value("redis", "pass_word", "")


# 保留 _ATT 相关的常量
SMS_ENDPOINT_ATT = "endpoint"
SMS_SIGN_NAME_ATT = "sign_name"
SMS_PHONE_NUMBERS_ATT = "phone_numbers"
DING_OPEN_CONVERSATION_ID_ATT = "open_conversation_id"
DING_APP_KEY_ATT = "app_key"
DING_APP_SECRET_ATT = "app_secret"
DING_ROBOT_CODE_ATT = "robot_code"

SERVER_HOST = ConfigAttribute.get_server_host()
SERVER_PORT = ConfigAttribute.get_server_port()
ENABLE_FILL = ConfigAttribute.get_enable_fill()
ENABLE_MINIO = ConfigAttribute.get_enable_minio()
ENABLE_CACHE = ConfigAttribute.get_enable_cache()
SMS_ENDPOINT = ConfigAttribute.get_sms_endpoint()
SMS_SIGN_NAME = ConfigAttribute.get_sms_sign_name()
SMS_PHONE_NUMBERS = ConfigAttribute.get_sms_phone_numbers()
DING_OPEN_CONVERSATION_ID = ConfigAttribute.get_ding_open_conversation_id()
DING_APP_KEY = ConfigAttribute.get_ding_app_key()
DING_APP_SECRET = ConfigAttribute.get_ding_app_secret()
DING_ROBOT_CODE = ConfigAttribute.get_ding_robot_code()
MINIO_ENDPOINT = ConfigAttribute.get_minio_endpoint()
MINIO_ACCESS_KEY = ConfigAttribute.get_minio_access_key()
MINIO_SECRET_KEY = ConfigAttribute.get_minio_secret_key()
REDIS_HOST = ConfigAttribute.get_redis_host()
REDIS_POST = ConfigAttribute.get_redis_port()
REDIS_USERNAME = ConfigAttribute.get_redis_username()
REDIS_PASSWORD = ConfigAttribute.get_redis_password()
